﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Needle.Utils;
using Needle.Utils.Collections;

namespace Needle.DevToolkit.Traits
{
    [Serializable]
    public sealed class ItemCollection : ObservableRichCollection<IItem>, IItemCollection
    {
        private IParent _Owner;
        public ItemCollection()
            : this(null)
        { }
        public ItemCollection(IParent owner)
        {
            _Owner = owner;
        }
        protected override void InsertItem(int index, IItem item)
        {
            Ensure.NotNull(item, "item");
            SetParent(item);
            base.InsertItem(index, item);
        }
        protected override void SetItem(int index, IItem item)
        {
            Ensure.NotNull(item, "item");
            SetParent(item);
            base.SetItem(index, item);
        }
        private void SetParent(IItem item)
        {
            if (_Owner == null)
                return;
            INestedItem nestedItem = null;
            if (item.TryGetTrait<INestedItem>(out nestedItem))
                nestedItem.Parent = _Owner;
        }

        public bool HasTrait<T>() where T : class
        {
            return GetTrait<T>() != null;
        }
        public T GetTrait<T>() where T : class
        {
            return this as T;
        }
        public bool TryGetTrait<T>(out T props) where T : class
        {
            props = GetTrait<T>();
            return props != null;
        }
        public IItem Last
        {
            get
            {
                if (this.Count < 1)
                    return null;
                return this[this.Count - 1];
            }
            set
            {
                if (this.Count < 1)
                    this.Add(value);
                else
                    this[this.Count - 1] = value;
            }
        }
        public IItem First
        {
            get
            {
                if (this.Count < 1)
                    return null;
                return this[0];
            }
            set
            {
                if (this.Count < 1)
                    this.Add(value);
                else
                    this[0] = value;
            }
        }
        public IEnumerable<T> GetItems<T>()
        {
            foreach (IItem item in this)
                if (item is T)
                    yield return (T)item;
        }

        public void Accept(IItemVisitor visitor)
        {
            foreach (var item in this)
                item.Accept(visitor);
        }


    }
}
